﻿using Core.RabbitMQ.Consumer;
using Core.RabbitMQ.Producer;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Reflection;


namespace Core.RabbitMQ.Extensions
{
    public static class RabbitMqServiceCollectionExtensions
    {
        public static IServiceCollection AddRabbitMqService(this IServiceCollection services, Action<RabbitMqOptions> rabbitMqOptions)
        {
            var options = new RabbitMqOptions();
            rabbitMqOptions(options);
            services.AddSingleton<IRabbitMqConnectionProxy>(obj =>
            {
                var logger = obj.GetRequiredService<ILogger<RabbitMqConnectionProxy>>();
                return new RabbitMqConnectionProxy(options, logger);
            });

            services.AddScoped<IRabbitMqProducer, RabbitMqProducer>();

            // 获取当前应用程序的DependencyContext
            var dependencyContext = DependencyContext.Load(Assembly.GetEntryAssembly());
            var libs = dependencyContext.CompileLibraries.Where(lib => lib is { Serviceable: false, Type: "project" });
            var implementedInterface = typeof(IConsumer<>);
            foreach (var lib in libs)
            {
                var assemblyTypes = Assembly.Load(lib.Name).GetTypes();
                var consumerTypes = assemblyTypes.Where(t => t.IsClass && !t.IsAbstract
                && t.GetTypeInfo().ImplementedInterfaces.Any(f => f.IsGenericType && f.GetGenericTypeDefinition() == implementedInterface)
                );
                foreach (Type consumerType in consumerTypes)
                {
                    services.AddSingleton(consumerType, consumerType);

                    var interfaceTypes = consumerType.GetTypeInfo().ImplementedInterfaces
                        .Where(f => f.GetTypeInfo().IsGenericType && f.GetGenericTypeDefinition() == implementedInterface).ToList();
                    
                    foreach (Type interfaceType in interfaceTypes)
                    {
                        services.AddSingleton(interfaceType, consumerType);
                        
                        var consumerServiceType=typeof(RabbitMqConsumerService<,>);
                        var generType = consumerServiceType.MakeGenericType(interfaceType.GenericTypeArguments.First(), consumerType);
                       
                        services.AddSingleton(typeof(IHostedService), generType);
                       
                    }
                }
            }
          
            return services;
        }
    }
}
